package com.googlecode.project4uz.encoder;

import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

import org.openrdf.rio.RDFFormat;

import com.googlecode.project4uz.interfaces.Loggable;

/**
 * Reprezentuje obslugiwane typy serializacji.
 * @author Daniel Kur
 */
public class Serializer implements Loggable {
	/**
	 * Serializacja tylko publicznych pol. 
	 */
	public static final Serializer PUBLIC = new Serializer("PUBLIC", "com.googlecode.project4uz.encoder.SerializerPublic");
	
	/**
	 * Serializacja beans'owa - getters&setters. 
	 */
	public static final Serializer BEANS = new Serializer("BEANS", "com.googlecode.project4uz.encoder.SerializerBean");
	
	/**
	 * Lista dostepnych typow serializacji. 
	 */
	private static final List<Serializer> TYPES = new ArrayList<Serializer>(2);
	
	static {
		TYPES.add(PUBLIC);
		TYPES.add(BEANS);
	}
	
	/**
	 * Unikalna nazwa serializatora. 
	 */
	private final String NAME;
	
	/**
	 * Nazwa klasy realizaujcej ten typ serializacji. 
	 */
	private final String CLASS;
	
	/**
	 * Tworzy nowy typ serializatora.
	 * @param name - nazwa serializatora.
	 * @param className - nazwa klasy realizujacej serializacje.
	 */
	Serializer(final String name, final String className) {
		this.NAME = name;
		this.CLASS = className;
	}
	
	/**
	 * Pobiera typ serializatora  na podstawie ciagu znakow.
	 * @param typeName - nazwa typu serializatora.
	 */
	public static final Serializer valueOf(final String typeName) {
        for(Serializer type : TYPES)
            if(type.NAME.equalsIgnoreCase(typeName))
                return type;
        return null;
    }
	
	/**
	 * Pobiera instancje klasy reprezentujacej dany typ serializatora.
	 * @param format - format RDF jakim zapisujemy do strumienia.
	 * @param output - strumien wyjsciowy dla wyniku.
	 */
	final AbstractSerializer getInstance(final RDFFormat format, final OutputStream output) {
		try {
			Constructor<?> c = Class.forName(CLASS).getDeclaredConstructor(RDFFormat.class, OutputStream.class);
			c.setAccessible(true);
			return (AbstractSerializer)c.newInstance(format, output);
		} catch(Exception e) {
			LOG.severe("Nie moge dostarczyc serializatora: " + NAME);
			System.exit(1);
			return null;
		}
	}
}
